接下來會學習從 0 到 1 建構自動化測試的流程:
需要基於 測試框架 編寫各種的測試,提交程式碼以後,可以自動觸發整個測試腳本的運行,繼而生成報告以及發送通知執行結果。
測試框架提供了一個建立架構的規則和函式庫,我們需要學習應用,使能夠更有效地 編寫、組織和執行測試 。測試框架有非常多,我這裡會選用 PyTest 作介紹,讓你了解挑選測試框架的時候需要知道什麼。待你對自動化測試有更好的理解以後,可以根據專案的需求,選擇適合的測試框架。
是一個基於 Python 的測試框架,需要在 Python 安裝 PyTest 套件
pip install pytest
現在先來建立資料夾 /tests
,然後再建一個 test_sample.py
測試 Module
# /tests/test_sample.py
def test_one():
# Pytest 使用的是 Python 內建的 assert 函數,用來判斷結果是否符合預期。
print("---test_one---")
assert 1 + 1 == 2
def test_two():
print("---test_two---")
assert 2 + 2 == 4
執行的指令:
# Terminal
# 執行資料夾內所有的 test case
pytest tests
# 執行 test_sample.py 內所有的 test case
pytest tests/test_sample.py
執行結果都會是:
============================ test session starts ============================
platform darwin -- Python 3.9.6, pytest-7.4.0, pluggy-1.3.0
rootdir: /xxxxxxx/pytest_sample
collected 2 items
tests/test_sample.py .. [100%]
============================= 2 passed in 0.02s =============================
還有一種常用的執行方法:
# -k 是用於選擇性運行指定測試用例的參數,可以指定匹配測試用例名稱的表達式
# 只執行符合表達式的 test case。
# 執行名稱含有 one 的 test case,所以只會執行 test_one()
pytest -k "one"
# 執行名稱含有 one 和 two 的 test case,所以沒有 test case 符合
pytest -k "one and two"
# 執行名稱含有 one 或 two 的 test case,所以 test_one() 和 test_two() 都會被執行
pytest -k "one or two"
執行的時候,有沒有發現為什麼都沒有看到 print() 的內容顯示?
執行 Pytest 時可以加入 -s
選項用於關閉 PyTest 默認的輸出捕獲。因為在默認情況下,PyTest 會捕獲並隱藏測試函數的標準輸出和標準錯誤輸出,以便在測試過程中更容易觀察測試結果。所以會看不到執行中的 output。因此加入 -s 就可以看到了。
執行 pytest -s
試試看,會發現 print()
的內容就會顯示了:
============================ test session starts ============================
platform darwin -- Python 3.9.6, pytest-7.4.0, pluggy-1.3.0
rootdir: /xxxxxxx/pytest_sample
collected 2 items
tests/test_sample.py ---test one---
.---test two---
.
============================ 2 passed in 0.02s ============================
另外再介紹一個也很常用的 -v
選項,可以顯示更多詳細信息。默認情況下,PyTest 只顯示簡單的點 .
來表示每個測試用例的運行結果。
執行 pytest -v
試試看,會發現原本的 .
會變成 function 的名稱和測試結果:
============================ test session starts ============================
platform darwin -- Python 3.9.6, pytest-7.4.0, pluggy-1.3.0
rootdir: /xxxxxxx/pytest_sample
collected 2 items
tests/test_sample.py::test_one PASSED [ 50%]
tests/test_sample.py::test_two PASSED
============================ 2 passed in 0.02s ============================
因此,一般想要顯示執行過程中的詳細資料和列印的內容,會在執行時同時加入 -s -v
的參數
test_*.py
或 *_test.py
命名的 Moduletest_*
命名的 function 來執行。Test
開頭的 Class,在 Class 中找出 test_*
命名的 Method 來執行。遵從以上規則命名測試 Module / Function / Class 和 Method 則可被 PyTest 視為 Test Cases。
pytest.ini
能改變 pytest
框架的執行規則。通過 pytest —help
可以查看 pytest.ini
中可以添加的參數與選項。
常用參數:
addopts
: 設定 pytest 執行時所帶的參數,避免每次執行都需要手動輸入。
就如上述提到的 -s -v
不想每次執行時都需要打這麼長的指令,可以寫加 pytest.ini
中
# pytest.ini
addopts = -s -v
testpaths
: 設定 test case 的路徑,只會搜索指定路徑下的測試 Module 來執行。
專案內或許會有多過一個存放 test case 的資料夾,這樣就可以指定執行哪些資料夾了。
# pytest.ini
addopts = -s -v
testpaths = tests
會在輸出看到指定的 testpaths
============================ test session starts ============================
platform darwin -- Python 3.9.6, pytest-7.4.0, pluggy-1.3.0
rootdir: /xxxxx/pytest_sample
configfile: pytest.ini
testpaths: tests
collected 2 items
tests_api/test_sample.py::test_one ---test one---
PASSED
tests_api/test_sample.py::test_two ---test two---
PASSED
============================ 2 passed in 0.01s ============================
markers
: 當使用 @pytest.marker
來標記用例,需要在 pytest.ini
中設置,否則會出現 Warning。Marker 主要用來把 Test Cases 分類,I.e. 可按種類 / Priority 等作分類。
# pytest.ini
marker =
web
api
p0
# test_markers.py
import pytest
@pytest.mark.web
def test_one():
assert True
@pytest.mark.api
def test_two():
assert True
@pytest.mark.p0
def test_three():
assert True
則可以在 Terminal 執行,應用參數 -m
帶入 marker,將會執行所有帶有該 marker 的 test cases。
# 執行 @pytest.mark.web 的 test cases,則為 test_one()
pytest -m "web"
# 執行 @pytest.mark.api 的 test cases,則為 test_two()
pytest -m "api"
# 執行 @pytest.mark.p0 的 test cases,則為 test_three()
pytest -m "po"
在一個專案我們會需要用到很多的套件,可以應用 requirements.txt
去記錄該專案會用到的套件以及相應的版本,方便應用專案的人可以一鍵安裝所需的套件,快速執行專案。
# requirements.txt
# <package>==<version>
pytest==7.4.0
selenium==4.10.0
# 安裝 requirements.txt 的套件指令
pip install -r requirements.txt
就這樣,PyTest 專案最基本的測試架構,就有以下內容了。
├── tests
└── test_*.py
├── pytest.ini
└── requirement.txt
接下來會先把整個測試流程串起來,再來擴展 PyTest 的測試架構。
常聽到有 TDD 和 BDD 測試框架,我們先了解一下什麼是 TDD 和 BDD:
TDD (Test Driven Development) 測試驅動開發
失敗的測試 (紅)
,然後編寫足夠的代碼使其 通過 (綠)
,最後對程式碼進行 重構
以保持其清晰度和簡潔性。BDD (Behavior Driven Development) 行為驅動開發
會發現其實 TDD 和 BDD 在講的開發模式,而不是測試框架。只是我們在進行不同的開發模式時,可以選用支援的測試框架。像是做開發系統的時候,可以套用測試框架 (I.e. PyTest, Unitest 等) 進行 TDD。但不會說是 TDD 測試框架,像我們 SDET 做的測試並不是 TDD,就只是單純的測試。
而 BDD 測試框架 (I.e. Cucumber, PyTest-bdd, Behave, Robot Framework, etc.) 強調使用自然語言 (I.e. Gerhkin) 描述測試,它特別為 BDD 開發模式而設,所以會說是 BDD 測試框架。
本篇文章應用的是 PyTest ,並非 BDD Framework,個人認為需要多寫一層 Gherkin 語法的 Feature 檔,某程度上是提高了開發的技術門檻。語句設計其實是一門藝術,如何可帶參數又能組織清晰的測試用例,還要顧及其重用性。在協作的時候,難度再進一步提高,各人有不一致的語句特色,組起來不知道會變成怎樣的文章。
亦因本文主要想讓大家學習怎樣做自動化測試,就先跳過這一 Part 了,如果有興趣的話,可以考慮應用 PyTest-bdd 套件作自學。